/*
 * <one line to give the program's name and a brief idea of what it does.>
 * Copyright (C) 2013  <copyright holder> <email>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#ifndef ALIGNVIEWER_H
#define ALIGNVIEWER_H

#include <QWidget>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QMetaType>
#include <QTimer>
#include <QLCDNumber>
#include <QPainterPath>

#include <baseclient.h>
#include <basedevice.h>
#include <indicom.h>
#include <libnova.h>
#include <math.h>

#define DEFAULT_HOST "localhost"
#define DEFAULT_PORT 7624
#define DEFAULT_DEVICE_NAME "EQMod Mount"

#define HMARGIN 20
#define VMARGIN 20
#define POLE_RETICLE 5
#define TELESCOPE_RETICLE 7
#define ALIGNED_RETICLE 2
#define POINTSET_TELESCOPE_RETICLE 2
#define POINTSET_TARGET_RETICLE 7
#define DEFAULT_TELESCOPE_COORD "ALIGNTELESCOPECOORDS"
#define DEFAULT_ALIGNED_COORD "EQUATORIAL_EOD_COORD"
#define DEFAULT_ALIGN_DATA "ALIGNDATA"
#define DEFAULT_POINTSET "POINTLIST"

#include "MountDisplay.h"

namespace Ui
{
class AlignViewer;
class MountDisplay;
}


  
class AlignViewer : public QWidget, public INDI::BaseClient
{
  Q_OBJECT
   
public:
  typedef struct AlignPoint {
    int index;
    double lst;
    double targetRA, targetDEC;
    double telescopeRA, telescopeDEC;
    double telescope_alt, telescope_az;
    double target_alt, target_az;
    QGraphicsItem *telescopeitem;
    QGraphicsItem *targetitem;   
  } AlignPoint;
  
class Face {
public:
  Face(int i0, int i1, int i2) 
  : index(3,-1), v(3), g(3) {
    index[0]=i0; index[1]=i1; index[2]=i2;
  }
  std::vector<int> index;
  std::vector<AlignPoint *> v;
  std::vector<QGraphicsItem *>g;
};

  AlignViewer();
  bool close();

signals:
  void obschanged(double lat, double lon);
  void lstchanged(double lst);
  void telescopecoordschanged(double tra, double tdec);
  void alignedcoordschanged(double ara, double adec);  
  void pointsetchanged(std::vector<AlignPoint> *ps);
  void faceschanged(std::vector<Face> *nf);
  
public slots:
  void connectMount();
  void disconnectMount();
  
  void setTelescopePropertyName(char *name);
  void setAlignedPropertyName(char *name);
  
  void changeobs(double lat, double lon);
  void changelst(double lst);
  void changetelescopecoords(double tra, double tdec);
  void changealignedcoords(double ara, double adec);
  void changepointset(std::vector<AlignPoint> *ps);
  void changefaces(std::vector<Face> *nf);
  void repaint();
  
protected:

    virtual void newDevice(INDI::BaseDevice *dp);
    virtual void newProperty(INDI::Property *property);
    virtual void removeProperty(INDI::Property *property);
    virtual void newBLOB(IBLOB *bp);
    virtual void newSwitch(ISwitchVectorProperty *svp);
    virtual void newNumber(INumberVectorProperty *nvp);
    virtual void newMessage(INDI::BaseDevice *dp, int messageID);
    virtual void newText(ITextVectorProperty *tvp);
    virtual void newLight(ILightVectorProperty *lvp);
    virtual void serverConnected();
    virtual void serverDisconnected(int exit_code);  
    AlignPoint *findPointIndex(int index);
    void toAltAz(double ra, double dec, double lst, double lon, double lat, double *alt, double *az);
    double range360(double r);
    QPointF getposAltAz(double alt, double az);
    QPainterPath *getArc(double alt1, double az1, double alt2, double az2);
    void drawPole();
    static const int TimerFreq = 1000;
    QTimer timer; 
    
private:
  Ui::AlignViewer* ui;
  char *indihost;
  unsigned int indiport;
  char *telescopecoordsname;
  char *alignedcoordsname;
  INDI::BaseDevice *indidevice;
  INDI::Property *telescopecoords, *alignedcoords;
  INDI::Property *aligndata;
  IBLOB *alignblob;
  double obs_lon, obs_lat, obs_lst;
  double telescope_ra, telescope_dec;
  double telescope_alt, telescope_az;
  double aligned_ra, aligned_dec;
  double aligned_alt, aligned_az;
  MountDisplay *mountdpy;
  MountDisplay *aligneddpy;
  QGraphicsScene scene;
  int gvwidth, gvheight;
  QPainterPath polereticle;
  QPen *scqpen;
  QPen scqpenblue;
  QPen scqpengreen;
  QPen scqpenyellow; 
  QPen scqpenorange;
  QPen scqpenbrightorange;
  QGraphicsEllipseItem *schorizon, *sctelescope, *scaligned;
  QGraphicsSimpleTextItem *sclon, *sclat;
  QGraphicsPathItem *scpolereticle;
  std::vector<AlignPoint> *pointset;
  std::vector<Face> *faces;
  double pointsetlon, pointsetlat;
};

#endif // ALIGNVIEWER_H

class QTimer;
